package wili.attrMapping.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import wili.attrMapping.core.del.AttsBean;
import wili.c.Ca;

/**
 *
 */
public abstract class Atts {
	/**
	 * 定义
	 */
	public final AttsDefine def;
	/**
	 * 
	 */
	public final UserConf conf;
	public final AttsFile file;
	/**
	 * 属性集所关联到的键值
	 */
	public final String key;
	/**
	 * 属性集所在对象名
	 */
	public final String objName;
	/**
	 * 属性集所在对象；实际场景下的对象实例，从中可解出实际属性集（本对象）
	 */
	public final Object obj;
	public final boolean isNewAtts;
	//
	public final int id = ++GenID;
	{
		if (id == 3)
			Ca.pause();
	}

	public Map<String, Object> toValueMap() {
		Map<String, Object> ret = new HashMap<>();
		for (Att att : list) {
			ret.put(att.name, att.value);
		}
		return ret;
	}

	public List<Att> list;
	/**
	 * value if this is leaf.
	 */
	public String value;
	/**
	 * value is old value, after update new value is newValue. new value if mapping
	 * to leaf attr.
	 */
	public String updateValue;
	public String mapingToValue;
	/**
	 * 属性集的映射属性集。
	 */
	public List<Atts> newAttsList;

	public Atts(AttsDefine def, AttsFile afile, String keyValue, Object obj, boolean isNew) {
		this.def = def;
		this.objName = def.objName;
		this.file = afile;
		this.key = keyValue;
		this.obj = obj;
		this.isNewAtts = isNew;
		this.conf = def.conf;
		Ca.asert(this.conf != null, "");
	}

	/**
	 * The kind of atts may affect mapping process.<br>
	 * eg. kind is "sales" or "purchase"<br>
	 * p类型的属性同s类型的属性可能共享一套规则表.但它们有差别，或当分开处理之。
	 */
	public abstract String getKind();

	public abstract List<Atts> findNewAttsList();

	public AttsObj toAtts() {
		return (AttsObj) this;
	}

	public AttsBean toBean() {
		return (AttsBean) this;
	}

	public Att att(String name) {
		for (Att at : list) {
			if (at.name.equals(name))
				return at;
		}
		return null;
	}

	public ValueMapingNode getRuleTarget(ValueMapingNode root) {
		ValueMapingNode ret = root.addOrMergeAtts(this, false);
		return ret;
	}

	public abstract void updateNewAtts(String mapingToValue);

	/**
	 * ...设新值（之后可写入文件）
	 *
	 * @param va
	 */
	public abstract void updateValue(String newValue);

	public abstract void addNewAtt(Atts atts);

	/**
	 * 在对旧对象的匹配中，当发现属性时，在此加入。
	 * 
	 * @param nam
	 * @param val
	 */
	public final void addAtt(String nam, String val) {
		if (list == null)
			list = new ArrayList<>();
		list.add(new Att(this, nam, val));
	}

	public <T> T getObject() {
		return (T) this.obj;
	}

	static int GenID;
}
